
package com.hlkj.pay.app.common.ext.local;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.MultipartFile;

import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.common.OssExtPt;
import com.hlkj.pay.app.common.ext.CommonExtConstant;
import com.hlkj.pay.dto.common.StorageConfig;
import com.hlkj.pay.enums.CommonEnum;

import cn.hutool.core.util.IdUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.StringPool;

/**
 * 本地存储
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = CommonExtConstant.CHANNEL_LOCAL)
public class LocalOssExtPt implements OssExtPt {

    @Value("${hlkj.upload.directory}")
    public String uploadDirectory;

    @Value("${hlkj.upload.secret.directory}")
    public String uploadSecretDirectory;

    /**
     * 本地上传
     *
     * @author fzr
     * @param multipartFile
     *            上传对象
     * @param key
     *            文件名称 20220331/122.jpg
     * @param ossEnum
     *            文件夹
     */
    public String upload(MultipartFile multipartFile, CommonEnum.OssEnum ossEnum, String key) throws IOException {
        // 映射目录
        String directory;
        switch (ossEnum) {
            case SECRET:
                directory = uploadSecretDirectory;
                break;
            default:
                directory = uploadDirectory;
        }
        // 映射目录
        if (directory == null || directory.equals("")) {
            throw new IOException("请配置上传目录like.upload-directory");
        }
        // 文件信息
        String saveName = key.split("/")[1];
        // 上传秘钥随机名称
        saveName = IdUtil.fastSimpleUUID()+"_"+saveName;
        String savePath = (directory + ossEnum.getFolder() + "/" + key.split("/")[0]).replace("\\", "/");
        // 创建目录
        File fileExist = new File(savePath);
        if (!fileExist.exists()) {
            if (!fileExist.mkdirs()) {
                throw new IOException("创建上传目录失败");
            }
        }
        // 保存文件
        try {
            File dest = new File(savePath, saveName);
            multipartFile.transferTo(dest);
        }
        catch (Exception e) {
            throw new IOException("上传文件失败:" + e.getMessage());
        }
        return savePath + StringPool.SLASH + saveName;
    }

    @Override
    public String upload(MultipartFile multipartFile, CommonEnum.OssEnum ossEnum, String key, StorageConfig storageConfig) throws IOException {
        return upload(multipartFile, ossEnum, key);
    }

    @Override
    public String upload(byte[] fileArray, CommonEnum.OssEnum ossEnum, String key, StorageConfig storageConfig) throws IOException {
        // 映射目录
        String directory;
        switch (ossEnum) {
            case SECRET:
                directory = uploadSecretDirectory;
                break;
            default:
                directory = uploadDirectory;
        }
        // String uploadHiddenDirectory =uploadHidden;
        // 映射目录
        if (directory == null || directory.equals("")) {
            throw new IOException("请配置上传目录like.upload-directory");
        }
        // 文件信息
        String saveName = key.split("/")[1];
        String savePath = (directory + ossEnum.getFolder() + "/" + key.split("/")[0]).replace("\\", "/");
        // String uploadHidden = (uploadHiddenDirectory + ossEnum.getFolder() + "/" +
        // key.split("/")[0]).replace("\\", "/");
        // 创建目录
        File fileExist = new File(savePath);
        if (!fileExist.exists()) {
            if (!fileExist.mkdirs()) {
                throw new IOException("创建上传目录失败");
            }
        }
        // 保存文件
        try (FileOutputStream fos = new FileOutputStream(new File(savePath, saveName))) {
            fos.write(fileArray); // 写入 byte 数组
            fos.flush(); // 确保所有数据写入
        }
        catch (IOException e) {
            throw new IOException("上传文件失败: " + e.getMessage(), e);
        }
        // 返回保存的文件路径
        return savePath + StringPool.SLASH + saveName;
    }

    @Override
    public String uploadZip(List<String> fileList, CommonEnum.OssEnum ossEnum, String key, StorageConfig storageConfig) throws IOException {
        // 映射目录
        String directory = uploadDirectory;
        // 映射目录
        if (directory == null || directory.equals("")) {
            throw new IOException("请配置上传目录like.upload-directory");
        }
        // 文件信息
        String saveName = key.split("/")[1];
        String zipFilePath = (directory + ossEnum.getFolder() + "/" + key.split("/")[0]).replace("\\", "/");
        // String uploadHidden = (uploadHiddenDirectory + ossEnum.getFolder() + "/" +
        // key.split("/")[0]).replace("\\", "/");
        // 创建目录
        File fileExist = new File(zipFilePath);
        if (!fileExist.exists()) {
            if (!fileExist.mkdirs()) {
                throw new IOException("创建上传目录失败");
            }
        }
        String zipFileName = zipFilePath + StringPool.SLASH + saveName;
        if(new File(zipFileName).exists()){
            new File(zipFileName).delete();
        }
        try {
            // 创建输出 ZIP 文件流
            try (FileOutputStream fos = new FileOutputStream(zipFileName); ZipOutputStream zos = new ZipOutputStream(fos)) {
                // 遍历要压缩的文件列表
                for (String filePath : fileList) {
                    // 创建文件对象
                    File file = new File(filePath);
                    if (file.exists()) {
                        // 创建 ZIP 条目
                        try (FileInputStream fis = new FileInputStream(file)) {
                            ZipEntry zipEntry = new ZipEntry(file.getName());
                            zos.putNextEntry(zipEntry);
                            // 读取文件内容并写入 ZIP 文件
                            byte[] buffer = new byte[1024];
                            int length;
                            while ((length = fis.read(buffer)) > 0) {
                                zos.write(buffer, 0, length);
                            }
                            zos.closeEntry(); // 关闭当前 ZIP 条目
                        }
                    }
                    else {
                        log.info("文件不存在 filePath:{}", filePath);
                    }
                }
                log.info("压缩完成，ZIP 文件路径:{}", zipFilePath);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            return "";
        }
        // 返回保存的文件路径
        return zipFileName;
    }
}
